package 锁;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author: 谢君臣
 * @Date: 2021/11/16-14:18
 * @version: 1.0
 * @function:
 */
public class ZeroEvenOdd {
    public void zero(IntConsumer printNumber) {
        lock.lock();
        try {
            while (i <= n) {
                if (state){
                    printNumber.accept(0);
                    state = !state;
                    if (i % 2 == 0)
                        conditionB.signal();
                    else
                        conditionC.signal();
                }else
                    conditionA.await();
            }
            conditionB.signal();
            conditionC.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void even(IntConsumer printNumber) {
        lock.lock();
        try {
            while (i <= n) {
                if (!state){
                    printNumber.accept(i++);
                    state = !state;
                    conditionA.signal();
                }else
                    conditionB.await();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void odd(IntConsumer printNumber) {
        lock.lock();
        try {
            while (i <= n) {
                if (!state){
                    printNumber.accept(i++);
                    state = !state;
                    conditionA.signal();
                }else
                    conditionC.await();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private int n;
    private volatile int i = 1;

    public ZeroEvenOdd(int n) {
        this.n = n;
    }

    public void setI(int i) {
        this.i = i;
    }

    public static Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();
    public Condition conditionC = lock.newCondition();
    public volatile boolean state = true;

    public class IntConsumer {

        public void accept(int i) {
            System.out.println(i);
        }
    }
}
